#include "herramienta.h"
#include "utilidadesgeometria.h"
#include "assert.h"
#include <QDebug>
#include "matematicas.h"

// HerramientaDesplazamiento /////////////////////////////////////////////////////

HerramientaDesplazamiento::HerramientaDesplazamiento()
{
    procesando = false;
}

HerramientaDesplazamiento::~HerramientaDesplazamiento()
{
}

void HerramientaDesplazamiento::activar()
{
    assert(observador != NULL); 

    observador->setCursor(Qt::OpenHandCursor);
}

void HerramientaDesplazamiento::procesarEventoPress(QMouseEvent *evento)
{
    assert(observador != NULL); 

    procesando = true; 
    puntoInicial = evento->pos();
    observador->setCursor(Qt::ClosedHandCursor);
}

void HerramientaDesplazamiento::procesarEventoMove(QMouseEvent *evento)
{
    assert(observador != NULL);

    if (procesando) {
        observador->desplazamientoTemporal(evento->pos().x() - puntoInicial.x(),  
                                           evento->pos().y() - puntoInicial.y());
    }
}

void HerramientaDesplazamiento::procesarEventoRelease(QMouseEvent *evento)
{
    assert(observador != NULL);

    observador->setCursor(Qt::OpenHandCursor);
    observador->desplazamiento(evento->pos().x() - puntoInicial.x(),
                               evento->pos().y() - puntoInicial.y());
    procesando = false;
}

#define PROPORCION_ZOOM .8

// HerramientaZoomEncuadre ////////////////////////////////////////////////////

HerramientaZoom::HerramientaZoom()
{
    procesando = false;
    colorSeleccion = QColor(255, 0, 127, 96);
}

HerramientaZoom::~HerramientaZoom()
{
}

void HerramientaZoom::activar()
{
    assert(observador != NULL);

    QPixmap pixmap(":/visor2d/Resources/cursor_lupa.png");
    observador->setCursor(QCursor(pixmap, 8, 8));
}

void HerramientaZoom::procesarEventoPress(QMouseEvent *evento)
{
    if (evento->button() == Qt::LeftButton) {
        procesando = true;
        rectangulo.setTopLeft(evento->pos());
        rectangulo.setBottomRight(evento->pos());
    }
}

void HerramientaZoom::procesarEventoMove(QMouseEvent *evento)
{
    assert(observador != NULL);

    if (!procesando) {
        return;
    }
    rectangulo.setBottomRight(evento->pos()); 
    ajustarRectangulo();

    observador->repintar();
}

#define MINIMO_LADO_ZOOM_CAJA 10

void HerramientaZoom::procesarEventoRelease(QMouseEvent *evento)
{
    assert(observador != NULL);

    rectangulo.setBottomRight(evento->pos());

    ajustarRectangulo();
    rectangulo = rectangulo.normalized();

    if (procesando && rectangulo.width() > MINIMO_LADO_ZOOM_CAJA && rectangulo.height() > MINIMO_LADO_ZOOM_CAJA) {
        observador->zoom(rectangulo); 
    } else if (evento->button() == Qt::LeftButton) {
        zoomCentrado(PROPORCION_ZOOM, evento->pos());
    } else if (evento->button() == Qt::RightButton) {
        zoomCentrado(1 / PROPORCION_ZOOM, evento->pos());
    } else {
        return;
    }

    procesando = false;
}

void HerramientaZoom::procesarEventoWheel(QWheelEvent* evento)
{
    int grados = evento->delta() / 8;
    int pasos = grados / 15;

    if (pasos == 0) {
        return;
    }
    
    QPoint centro = evento->pos(); 

    zoomCentrado(pow(PROPORCION_ZOOM, pasos), centro);
}

void HerramientaZoom::zoomCentrado(double proporcion, QPoint centro)
{
    QRect encuadre = observador->getRectanguloPixeles();
    int ancho = encuadre.width() * proporcion;
    int alto = encuadre.height() * proporcion;

    QRect nuevoEncuadre = UtilidadesGeometria::rectanguloRedimensionado(encuadre, ancho, alto, centro).toRect();

    observador->zoom(nuevoEncuadre);
}

void HerramientaZoom::dibujar(QPainter* painter)
{
    if (!procesando) {
        return;
    }
    QRect rectanguloNormalizado = rectangulo.normalized();
    if (rectanguloNormalizado.width() > MINIMO_LADO_ZOOM_CAJA && rectanguloNormalizado.height() > MINIMO_LADO_ZOOM_CAJA) {
        painter->fillRect(rectanguloNormalizado, colorSeleccion);
    }
}
// HerramientaZoomEncuadreEjeX ////////////////////////////////////////////////

void HerramientaZoomEncuadreEjeX::ajustarRectangulo()
{
    QRect rectangulTotal = observador->getRectanguloPixeles();

    rectangulo.setTop(rectangulTotal.top());
    rectangulo.setBottom(rectangulTotal.bottom());
}

// HerramientaZoomElastico  ///////////////////////////////////////////////////

HerramientaZoomElastico::HerramientaZoomElastico()
{
    procesando = false;
}

HerramientaZoomElastico::~HerramientaZoomElastico()
{
}

void HerramientaZoomElastico::procesarEventoPress(QMouseEvent *evento)
{
    procesando = true;
    puntoInicial = evento->pos();
}

void HerramientaZoomElastico::procesarEventoMove(QMouseEvent *evento)
{
    if (!procesando) {
        return;
    }
    QRect rectanguloZoom = calcularRectanguloZoom(evento->pos());
    observador->zoomTemporal(rectanguloZoom.normalized());
}

void HerramientaZoomElastico::procesarEventoRelease(QMouseEvent *evento)
{
    if (!procesando) {
        return;
    }
    QRect rectanguloZoom = calcularRectanguloZoom(evento->pos());
    observador->zoom(rectanguloZoom.normalized());
    procesando = false;
}

// HerramientaZoomElasticoHorizontal /////////////////////////////////////////////

void HerramientaZoomElasticoHorizontal::activar()
{
    assert(observador != NULL);
    observador->setCursor(Qt::SizeHorCursor);
}

QRect HerramientaZoomElasticoHorizontal::calcularRectanguloZoom(const QPoint& puntoActual)
{
    QRect rectangulTotal = observador->getRectanguloPixeles();

    int desplazamientoX = (puntoActual.x() - puntoInicial.x()) / 2;
     
    if (desplazamientoX * 3 >= rectangulTotal.width()) {
        desplazamientoX = rectangulTotal.width() / 3;
    }
    
    return rectangulTotal.adjusted(desplazamientoX, 0, -desplazamientoX, 0);
}

// HerramientaZoomElasticoVertical /////////////////////////////////////////////

void HerramientaZoomElasticoVertical::activar()
{
    assert(observador != NULL);
    observador->setCursor(Qt::SizeVerCursor);
}

QRect HerramientaZoomElasticoVertical::calcularRectanguloZoom(const QPoint& puntoActual)
{
    QRect rectangulTotal = observador->getRectanguloPixeles();

    int desplazamientoY =  (puntoActual.y() - puntoInicial.y()) / 2;
    if (desplazamientoY * 3 >= rectangulTotal.height()) {
        desplazamientoY = rectangulTotal.height() / 3;
    }
   
    return rectangulTotal.adjusted(0, desplazamientoY, 0, -desplazamientoY);
}

// HerramientaInformacion /////////////////////////////////////////////////////

void HerramientaInformacion::activar()
{
    assert(observador != NULL);
    observador->setCursor(Qt::WhatsThisCursor);
}

void HerramientaInformacion::procesarEventoPress(QMouseEvent *evento)
{    
    assert(observador != NULL);
    observador->mostrarInformacion(evento->pos());
}
